package com.zx._06_JVM.chapter_01_classloader.classloader;

import java.io.IOException;
import java.io.InputStream;

public class MyClassloaderTest {

    public static void main(String[] args)
            throws ClassNotFoundException, InstantiationException, IllegalAccessException {
        // 自定义classloader，不使用双亲委派
        ClassLoader myClassLoader = new ClassLoader() {
            @Override
            public Class<?> loadClass(String name) throws ClassNotFoundException {
                String fileName = name.substring(name.lastIndexOf(".") + 1) + ".class";
                try (InputStream is = getClass().getResourceAsStream(fileName)) {
                    if (is == null) {
                        return super.loadClass(name);
                    }
                    byte[] b = new byte[is.available()];
                    is.read(b);
                    return defineClass(name, b, 0, b.length);
                } catch (IOException e) {
                    throw new ClassNotFoundException(name);
                }
            }
        };

        Class<?> aClass = myClassLoader.loadClass(
                "com.zx._06_JVM.chapter_01_classloader.classloader.MyClassloaderTest");
        Object o = aClass.newInstance();

        System.out.println("自定义classloader加载的class：" + aClass.hashCode());//13329486
        System.out.println("自定义classloader加载的class：" + o.getClass().hashCode());//13329486
        System.out.println("系统本身加载的class：" + MyClassloaderTest.class.hashCode());//1870647526
        System.out.println(o instanceof MyClassloaderTest);//false。 不是同一个类

        // 系统默认classloader，就是 jdk.internal.loader.ClassLoaders$AppClassLoader
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader.getClass().getName());

        // 这个类本身的classloader jdk.internal.loader.ClassLoaders$AppClassLoader
        ClassLoader defaultClassLoader = MyClassloaderTest.class.getClassLoader();
        System.out.println(defaultClassLoader.getClass().getName());

        test01();
    }

    // 获得classloader
    private static void test01() {
        System.out.println("@@@@@@@@@@@@@@@@");
        //获取系统类加载器 jdk.internal.loader.ClassLoaders$AppClassLoader@1f89ab83
        ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
        System.out.println(systemClassLoader);

        //获取其上层: 扩展类加载器  jdk.internal.loader.ClassLoaders$PlatformClassLoader@4bec1f0c
        ClassLoader extClsLoader = systemClassLoader.getParent(); //上层并不是父类
        System.out.println(extClsLoader);

        String extDirs = System.getProperty("java.ext.dirs");
        System.out.println("java.ext.dirs:" + extDirs);

        //获取其上层 bootstrapClsLoader 获取不到引导类加载器 null
        ClassLoader bootstrapClsLoader = extClsLoader.getParent();
        System.out.println(bootstrapClsLoader);

        //对于用户自定义类来说:使用系统类加载器加载  jdk.internal.loader.ClassLoaders$PlatformClassLoader@4bec1f0c
        ClassLoader classLoader = MyClassloaderTest.class.getClassLoader();
        System.out.println(classLoader);

        //String类使用引导类加载器  Java核心类库都是用引导类加载器加载
        ClassLoader stringLoader = String.class.getClassLoader();
        System.out.println(stringLoader); //null
    }


    // 操作Bootstrap ClassLoader。因为Bootstrap ClassLoader是jvm底层实现的无法获得实例
    // 但是可以ClassLoader类对其进行操作
    private static void test02() {
    }
}
